﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Jinjia.Approve.Common.Enum;
using Jinjia.Approve.Entity.Entity.JJFlow;
using Jinjia.Approve.IRepository.JJFlow;
using Jinjia.Approve.IService;
using Jinjia.Approve.IService.JJFlow;
using Jinjia.Approve.IService.JJFlow.Action;
using Jinjia.Approve.Model.Input.JJFlow;
using Jinjia.Approve.Model.VM;
using Jinjia.Approve.Model.VM.JJFlow;
using Jinjia.Approve.Model.VM.JJFlow.DTO;
using JinJia.Core.Base.Exceptions;

namespace Jinjia.Approve.Service.JJFlow.Action
{
    public class JJFlowActionSendBack : JJFlowActionGoTo, IJJFlowActionSendBack
    {
        private readonly IJJFlowNodeService _jjFlowNodeService;
        private readonly IFlowNodeReferenceRepository _flowNodeReferenceRepository;
        private readonly IJJFlowCommentService _jjFlowCommentService;
        private readonly IFlowInstanceEmpRepository _flowInstanceEmpRepository;

        public JJFlowActionSendBack(IJJFlowInstanceService jjFlowInstanceService,
            IJJFlowTrackService jjFlowTrackService,
            IJJFlowNodeService jjFlowNodeService,
            IFlowNodeReferenceRepository flowNodeReferenceRepository,
            IJJFlowCommentService jjFlowCommentService,
            IFlowInstanceEmpRepository flowInstanceEmpRepository) : base(jjFlowInstanceService,
            jjFlowTrackService)
        {
            _jjFlowNodeService = jjFlowNodeService;
            _flowNodeReferenceRepository = flowNodeReferenceRepository;
            _jjFlowCommentService = jjFlowCommentService;
            _flowInstanceEmpRepository = flowInstanceEmpRepository;
        }

        public async Task<NodeInfo> SendBack(SendBackRequest request, JjFlowInstanceVM instance, int user_id)
        {
            #region 判断节点

            var all_planned_nodes = await _jjFlowNodeService.GetNodesPlan(instance.Id);
            var current_node_index = all_planned_nodes.FindIndex(m => m.id == instance.CurrentNodeId);
            var back_node_index = current_node_index - 1; //默认退回上一节点
            if (request.node_id > 0)
            {
                back_node_index = all_planned_nodes.FindIndex(m => m.id == request.node_id);
                if (back_node_index == -1)
                {
                    throw new BusinessException("退回节点不存在");
                }
                else if (back_node_index >= current_node_index && request.remark != "review_cancel" && request.modular_key != "celeb_promote") //媒介复审撤回需要略过此校验，将待复审撤回到审批通过
                {
                    throw new BusinessException("只能退回已审批的节点");
                }
            }

            if (back_node_index < 0)
            {
                throw new BusinessException("无法退回");
            }

            #endregion

            #region 修改节点 & 增加记录

            var current_node = all_planned_nodes[current_node_index];
            var back_node = all_planned_nodes[back_node_index];
            //修改当前节点
            instance.UpdateUserId = user_id;
            instance.UpdateTime = DateTime.Now;
            instance.CurrentNodeId = back_node.id;
            if (instance.Status == "10") //由于拒绝并没有修改当前节点，所以退回只需将状态恢复为审批中即可
            {
                instance.Status = "0";
            }

            await _jjFlowInstanceService.Save(instance);
            //增加退回记录
            var reference_list = await _flowNodeReferenceRepository.GetReferences(instance.Id);
            var reference_model = reference_list.FirstOrDefault(x => x.node_id == current_node.id);
            if (reference_model == null)
            {
                throw new BusinessException("未找到该节点预计轨迹！");
            }

            reference_list = reference_list.Where(x => x.sequence > reference_model.sequence).ToList();
            var reference_node = reference_list.FirstOrDefault();
            var next_reference_node = all_planned_nodes.First(x => x.id == reference_node?.node_id);

            await _jjFlowTrackService.Save(new JjFlowTrackVM()
            {
                instance_id = instance.Id,
                operation_result = next_reference_node.node_type,
                node_id = next_reference_node.id,
                node_name = next_reference_node.node_name,
                action_type = (int)EnumDb.JJFlowOperationTypeEnum.Approve,
                action_type_name = string.IsNullOrWhiteSpace(request.remark) ? $"审批退回" : request.remark,
                from_emp = user_id.ToString(),
                update_user_id = user_id,
                create_user_id = user_id
            });

            await _jjFlowCommentService.Save(new JJFlowCommentVM()
            {
                comment = request.remark,
                node_name = next_reference_node.node_name,
                node_action = string.IsNullOrWhiteSpace(request.remark) ? $"审批退回" : request.remark,
                is_append = 0,
                biz_order_id = instance.BizOrderId,
                modular_key = instance.ModularKey,
                create_time = DateTime.Now,
                update_time = DateTime.Now,
                update_user_id = user_id,
                create_user_id = user_id,
            });

            await _jjFlowCommentService.UpdateIsAppend(instance.BizOrderId, instance.ModularKey);

            #endregion

            #region 恢复审批记录

            //当前节点和退回节点之间的节点
            var nodeIds = new List<int>();
            for (var i = back_node_index; i < current_node_index; i++)
            {
                nodeIds.Add(all_planned_nodes[i + 1].id);
            }

            await _flowInstanceEmpRepository.RecordReset(instance.Id, nodeIds);

            #endregion

            #region 返回下一个节点

            var next_node = all_planned_nodes[back_node_index + 1];
            return new NodeInfo()
            {
                instance_id = instance.Id,
                isComplete = false,
                emp_user = await _flowInstanceEmpRepository.GetInstanceNodeEmp(next_node.id, instance.Id, next_node.template_id),
                info = new BaseBoVM<Node>(next_node)
            };

            #endregion
        }
    }
}